home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 1 / ETO Development Tools 1.iso / Essentials / Developer Essentials Jul 90 / Programming / MPW Dynamo 3.0 / dynamo.includes / rt.macros < prev    next >
Encoding:
Text File  |  1990-03-17  |  38.1 KB  |  1,723 lines  |  [TEXT/MPS ]

  1. *******************************************************
  2. *                        *
  3. * DYNAMO                        *
  4. *                        *
  5. * Apple II 8-bit runtime macros.            *
  6. * Copyright (C) 1990 Apple Computer.        *
  7. * Version 3.0                    *
  8. *                        *
  9. * Written by Eric Soldan, Apple II DTS        *
  10. *                        *
  11. *******************************************************
  12.  
  13. * These macros are interfaces for the runtime routines associated with them.
  14. * The runtime routines handle up to 128 integer variables, and up to 256
  15. * strings.  The integer functions are simple add,sub,mul,div, and others.
  16. * These others include mass-initialization, min, max, print decimal, etc.
  17. * The string functions are most of what is available in AppleSoft, in
  18. * various forms.  There is also support for multi-dimension arrays.
  19.  
  20. * The principle of the runtime routines is that the xreg holds a destination
  21. * variable number (for ints: 0-254, for strings: 0-255).  All runtimes preserve
  22. * the xreg, therefore, you can do multiple operations to a single variable
  23. * without having to reload the xreg.  The values that are used on the xreg
  24. * variable (the source data), is one of 3 forms for integers:
  25. *    1. 1-byte value
  26. *    2. 2-byte value
  27. *    3. 2-byte integer variable.
  28. * 1-byte values are placed in the acc.  2-byte values are placed in the acc,y
  29. * (acc=lo, y=hi).  2-byte integer variables have the variable number placed in
  30. * the yreg.  (The yreg is not preserved by the runtime routines.)
  31. * Once the source data is loaded (in acc, acc-y, or y), the proper call to the
  32. * runtime routines is made.  The 'proper' routine is based on the type of data
  33. * the source is.  (If the source is a variable, and we are adding, the macro
  34. * will call the addvar routine.)
  35.  
  36. * Strings are also referenced by number.  There are 3 tables for strings:
  37. *    1. String length table.
  38. *    2. Max string length table.
  39. *    3. Pointer table.
  40. * So, each string takes up four bytes, plus however long the max string length
  41. * is.  Having the pointer allows the program to point into memory that was
  42. * never loaded or initialized.  This can save time loading the application from
  43. * disk.  The string routines will never overwrite the buffer space alloced for
  44. * them.  The string will be truncated.  So, you can append strings without
  45. * worry about clobbering memory.
  46.  
  47.  
  48. *****************************************************************
  49. *****************************************************************
  50. *****************************************************************
  51.  
  52. * These macros are called by other macros in this file.
  53.  
  54. ***************************************
  55.  
  56.     MACRO
  57.     acorm    &op
  58.     lclc    &str
  59. &str    setc    &op
  60.     if    &substr(&str,1,1)='#' goto .imm
  61.     if    &substr(&str,1,1)<>'*' then
  62.     aerror    'non-variable parameter must start with a # or *'
  63.     mexit
  64.     endif
  65. &str    setc    &substr(&str,2,999)
  66.     lcla    &deref
  67. &deref    seta    0
  68. .a    if    &substr(&str,1,1)<>'*' goto .b
  69. &str    setc    &substr(&str,2,999)
  70. &deref    seta    &deref+1
  71.     goto    .a
  72. .b    if    &substr(&str,1,1)='<' then
  73. &str    setc    &substr(&str,2,999)
  74.     endif
  75.     if    &deref>0 then
  76.     lda    &str+1
  77.     sta    aderefz+2
  78.     endif
  79.     lda    &str
  80. .d    if    &deref>0 then
  81.     jsr    aderef
  82. &deref    seta    &deref-1
  83.     goto    .d
  84.     endif
  85.     mexit
  86. .imm
  87. &str    setc    &substr(&str,2,999)
  88.     if    &substr(&str,1,1)='<' then
  89. &str    setc    &substr(&str,2,999)
  90.     endif
  91.     lda    #<&str
  92.     MEND
  93.  
  94. ***************************************
  95.  
  96.     MACRO
  97.     ycorm    &op
  98.     lclc    &str
  99. &str    setc    &op
  100.     if    &substr(&str,1,1)='#' goto .imm
  101.     if    &substr(&str,1,1)<>'*' then
  102.     aerror    'non-variable parameter must start with a # or *'
  103.     mexit
  104.     endif
  105. &str    setc    &substr(&str,2,999)
  106.     lcla    &deref
  107. &deref    seta    0
  108. .a    if    &substr(&str,1,1)<>'*' goto .b
  109. &str    setc    &substr(&str,2,999)
  110. &deref    seta    &deref+1
  111.     goto    .a
  112. .b    if    &substr(&str,1,1)='<' then
  113. &str    setc    &substr(&str,2,999)
  114.     endif
  115.     if    &deref>0 then
  116.     ldy    &str+1
  117.     sty    yderefz+2
  118.     endif
  119.     ldy    &str
  120. .d    if    &deref>0 then
  121.     jsr    yderef
  122. &deref    seta    &deref-1
  123.     goto    .d
  124.     endif
  125.     mexit
  126. .imm
  127. &str    setc    &substr(&str,2,999)
  128.     if    &substr(&str,1,1)='<' then
  129. &str    setc    &substr(&str,2,999)
  130.     endif
  131.     ldy    #<&str
  132.     MEND
  133.  
  134. ***************************************
  135.  
  136.     MACRO
  137.     aycorm    &op
  138. ayisbyte    set    0
  139.     lclc    &str
  140. &str    setc    &op
  141.     if    &substr(&str,1,1)='#' goto .imm
  142.     if    &substr(&str,1,1)<>'*' then
  143.     aerror    'non-variable parameter must start with a # or *'
  144.     mexit
  145.     endif
  146. &str    setc    &substr(&str,2,999)
  147.     lcla    &deref
  148. &deref    seta    0
  149. .a    if    &substr(&str,1,1)<>'*' goto .b
  150. &str    setc    &substr(&str,2,999)
  151. &deref    seta    &deref+1
  152.     goto    .a
  153. .b    if    &substr(&str,1,1)='<' then
  154. ayisbyte    set    1
  155. &str    setc    &substr(&str,2,999)
  156.     endif
  157.     lda    &str
  158.     if    &deref>0 goto .c
  159.     if    ayisbyte=1 goto .d
  160. .c    ldy    &str+1
  161. .d    if    &deref>0 then
  162.     jsr    deref
  163. &deref    seta    &deref-1
  164.     goto    .d
  165.     endif
  166.     mexit
  167. .imm
  168. &str    setc    &substr(&str,2,999)
  169.     if    &substr(&str,1,1)='<' then
  170. ayisbyte    set    1
  171. &str    setc    &substr(&str,2,999)
  172.     endif
  173.     lda    #<&str
  174.     if    ayisbyte=0 then
  175.     ldy    #>&str
  176.     endif
  177.     MEND
  178.  
  179.  
  180. *****************************************************************
  181. *****************************************************************
  182. *****************************************************************
  183.  
  184.  
  185.     MACRO
  186. &lab    _int    &op
  187. &lab    aycorm    &op
  188.     if    ayisbyte=1 then
  189.     ldy    #0
  190.     endif
  191.     MEND
  192.  
  193.  
  194. *****************************************************************
  195.  
  196.  
  197.     MACRO
  198. &lab    _ptr    &op
  199. &lab    aycorm    &op
  200.     if    ayisbyte=1 then
  201.     ldy    #0
  202.     endif
  203.     MEND
  204.  
  205.  
  206. *****************************************************************
  207.  
  208.  
  209.     MACRO
  210. &lab    _byte    &op
  211. &lab    acorm    &op
  212.     MEND
  213.  
  214.  
  215. *****************************************************************
  216. *****************************************************************
  217. *****************************************************************
  218.  
  219.  
  220. * This macro initializes everything necessary in the runtime and runtime
  221. * macros.  It initializes global macro variables and resets everything
  222. * in the runtime so the application can resume if the user presses a reset.
  223.     MACRO
  224. &lab    _rtreset
  225. &lab    jsr    rtreset
  226.     MEND
  227.  
  228.  
  229. ***************************************
  230.  
  231.  
  232. * This macro is used to turn on the hi-bit for characters that are sent to rtcout.
  233.     MACRO
  234. &lab    _hibitchrs
  235. &lab    jsr    hibitchrs
  236.     MEND
  237.  
  238.  
  239. ***************************************
  240.  
  241.  
  242. * This macro is used to turn off the hi-bit for characters that are sent to rtcout.
  243.     MACRO
  244. &lab    _lowbitchrs
  245. &lab    jsr    lowbitchrs
  246.     MEND
  247.  
  248.  
  249. ***************************************
  250.  
  251.  
  252. * This macro is used to make sure that characters sent to rtcout are used as-is.  There
  253. * will be no modification of the hi-bit.
  254.     MACRO
  255. &lab    _regchrs
  256. &lab    jsr    regchrs
  257.     MEND
  258.  
  259.  
  260. ***************************************
  261.  
  262.  
  263. * This macro prints a character.  This character is either already in the acc
  264. * (no operand), or what is described by the operand.  The operand can either
  265. * be an absolute or a value in memory.
  266. * (acorm means load Acc with a Constant OR Memory value).
  267.     MACRO
  268. &lab    _rtcout    &op
  269. &lab
  270.     if    &op='' goto .jsr
  271.     acorm    &op
  272. .jsr    jsr    rtcout
  273.     MEND
  274.  
  275.  
  276. ***************************************
  277.  
  278.  
  279. * This macro prints ascii data following the _write macro.  The write routine
  280. * works by using the return address as a pointer to the ascii data.  The ascii
  281. * data is terminated with a 0 (C-string style).  When the write routine
  282. * encounters a 0, it sets the return address so the when an rts is executed,
  283. * it returns to the code following the 0 terminator.  As many parameters as
  284. * are desired can be passed to this routine.  If the ascii data is more than
  285. * 1 line, end it with a comma,backslash to indicate line continuation.
  286.     MACRO
  287. &lab    _write
  288. &lab    
  289.     if    &syslist[1]='' then
  290.     aerror    '_write:  must have at least one parameter'
  291.     mexit
  292.     endif
  293.     jsr    write
  294.     lcla    &i,&n
  295. &i    seta    1
  296. &n    seta    &nbr(&syslist)
  297. .a    dc.b    &syslist[&i]
  298. &i    seta    &i+1
  299.     if    &i<=&n goto .a
  300.     dc.b    0
  301.     MEND
  302.  
  303.  
  304. ***************************************
  305.  
  306.  
  307. * This macro prints a carriage return.
  308.     MACRO
  309. &lab    _writecr
  310. &lab    jsr    writecr
  311.     MEND
  312.  
  313.  
  314. ***************************************
  315.  
  316.  
  317. * This macro prints a c string pointed to by the operand.
  318.     MACRO
  319. &lab    _wrcstr    &op
  320. &lab    aycorm    &op
  321.     if    ayisbyte=1 then
  322.     ldy    #0
  323.     endif
  324.     jsr    wrcstr
  325.     MEND
  326.  
  327.  
  328. ***************************************
  329. ***************************************
  330. ***************************************
  331.  
  332.  
  333. * This macro sets signed mode.  Printing decimal numbers is affected by this.
  334.     MACRO
  335. &lab    _signed
  336. &lab    jsr    signed
  337.     MEND
  338.  
  339.  
  340. ***************************************
  341.  
  342.  
  343. * This macro sets unsigned mode.  Printing decimal numbers is affected by this.
  344.     MACRO
  345. &lab    _unsigned
  346. &lab    jsr    unsigned
  347.     MEND
  348.  
  349.  
  350. ***************************************
  351.  
  352.  
  353. * This macro does a two's compliment on the variable.
  354.     MACRO
  355. &lab    _chngsgn
  356. &lab    jsr    chngsgn
  357.     MEND
  358.  
  359.  
  360. ***************************************
  361.  
  362.  
  363. * This macro prints a 1-byte decimal value.  This value is either already in
  364. * the acc (no operand), or what is described by the operand.  The operand can
  365. * either be an absolute or a value in memory.
  366.     MACRO
  367. &lab    _decoutl    &op
  368. &lab    
  369.     if    &op='' goto .jsr
  370.     acorm    &op
  371. .jsr    jsr    decoutl
  372.     MEND
  373.  
  374.  
  375. ***************************************
  376.  
  377.  
  378. * This macro prints a 2-byte decimal value.  This value is stored in a
  379. * variable.  The variable number is either already in the xreg (no operand),
  380. * or is determined by the operand.
  381.     MACRO
  382. &lab    _vdecout    &op
  383. &lab    
  384.     if    &op='' goto .jsr
  385.     ldx    #<&op
  386. .jsr    jsr    vdecout
  387.     MEND
  388.  
  389.  
  390. ***************************************
  391.  
  392.  
  393. * This macro prints a 1- or 2-byte decimal value.  This value is either already
  394. * in the acc,y (no operand), or what is described by the operand.  The operand
  395. * can either be an absolute or a value in memory.
  396.     MACRO
  397. &lab    _decout    &op
  398. &lab    
  399.     if    &op='' goto .jsr
  400.     aycorm    &op
  401.     if    ayisbyte=1 then
  402.     jsr    decoutl
  403.     mexit
  404.     endif
  405. .jsr    jsr    decout
  406.     MEND
  407.  
  408.  
  409. ***************************************
  410.  
  411.  
  412. * This macro sets pad mode for hex.  The value is either already in the acc
  413. * (no operand), or what is described by the operand.  The operand can either
  414. * be an absolute or a value in memory.  Printing hex numbers is affected by
  415. * this.
  416.     MACRO
  417. &lab    _hexpad    &op
  418. &lab    
  419.     if    &op='' goto .jsr
  420.     acorm    &op
  421. .jsr    jsr    hexpad
  422.     MEND
  423.  
  424.  
  425. ***************************************
  426.  
  427.  
  428. * This macro sets no pad mode for hex.  Printing hex numbers is affected by
  429. * this.
  430.     MACRO
  431. &lab    _hexnopad
  432. &lab    jsr    hexnopad
  433.     MEND
  434.  
  435.  
  436. ***************************************
  437.  
  438.  
  439. * This macro prints a 1-byte hex value.  This value is either already in the
  440. * acc (no operand), or what is described by the operand.  The operand can
  441. * either be an absolute or a value in memory.
  442.     MACRO
  443. &lab    _hexoutl    &op
  444. &lab    
  445.     if    &op='' goto .jsr
  446.     acorm    &op
  447. .jsr    jsr    hexoutl
  448.     MEND
  449.  
  450.  
  451. ***************************************
  452.  
  453.  
  454. * This macro prints a 2-byte hex value.  This value is stored in a variable.
  455. * The variable number is either already in the xreg (no operand), or is
  456. * determined by the operand.
  457.     MACRO
  458. &lab    _vhexout    &op
  459. &lab    
  460.     if    &op='' goto .jsr
  461.     ldx    #<&op
  462. .jsr    jsr    vhexout
  463.     MEND
  464.  
  465.  
  466. ***************************************
  467.  
  468.  
  469. * This macro prints a 1- or 2-byte hex value.  This value is either already in
  470. * the acc,y (no operand), or what is described by the operand.  The operand can
  471. * either be an absolute or a value in memory.
  472.     MACRO
  473. &lab    _hexout    &op
  474. &lab    
  475.     if    &op='' goto .jsr
  476.     aycorm    &op
  477.     if    ayisbyte=1 then
  478.     ldy    #0
  479.     endif
  480. .jsr    jsr    hexout
  481.     MEND
  482.  
  483.  
  484. ***************************************
  485.  
  486.  
  487. * This macro adds a variable to the destination variable.  If there is no
  488. * op1, then the destination variable number is assumed to be in the xreg.
  489. * If there is no op2, then the source variable number is assumed to be in
  490. * the yreg.
  491.     MACRO
  492. &lab    _addvar    &op1,&op2
  493. &lab
  494.     if    &op1='' goto .a
  495.     ldx    #<&op1
  496. .a    if    &op2='' goto .jsr
  497.     ldy    #<&op2
  498. .jsr    jsr    addvar
  499.     MEND
  500.  
  501.  
  502. ***************************************
  503.  
  504.  
  505. * This macro adds a 1-byte value to the destination variable.  If there is
  506. * no op1, then the destination variable number is assumed to be in the xreg.
  507. * If there is no op2, then the value is assumed to be in the acc.
  508.     MACRO
  509. &lab    _addl    &op1,&op2
  510. &lab
  511.     if    &op1='' goto .a
  512.     ldx    #<&op1
  513. .a    if    &op2='' goto .jsr
  514.     acorm    &op2
  515. .jsr    jsr    addconl
  516.     MEND
  517.  
  518.  
  519. ***************************************
  520.  
  521.  
  522. * This macro adds a 2-byte value to the destination variable.  If there is
  523. * no op1, then the destination variable number is assumed to be in the xreg.
  524. * If there is no op2, then the value is assumed to be in acc,y.
  525.     MACRO
  526. &lab    _add    &op1,&op2
  527. &lab
  528.     if    &op1='' goto .a
  529.     ldx    #<&op1
  530. .a    if    &op2='' goto .jsr
  531.     aycorm    &op2
  532.     if    ayisbyte=1 then
  533.     jsr    addconl
  534.     mexit
  535.     endif
  536. .jsr    jsr    addcon
  537.     MEND
  538.  
  539.  
  540. ***************************************
  541.  
  542.  
  543. * This macro subtracts a variable from the destination variable.  If there is
  544. * no op1, then the destination variable number is assumed to be in the xreg.
  545. * If there is no op2, then the source variable number is assumed to be in
  546. * the yreg.
  547.     MACRO
  548. &lab    _subvar    &op1,&op2
  549. &lab
  550.     if    &op1='' goto .a
  551.     ldx    #<&op1
  552. .a    if    &op2='' goto .jsr
  553.     ldy    #<&op2
  554. .jsr    jsr    subvar
  555.     MEND
  556.  
  557.  
  558. ***************************************
  559.  
  560.  
  561. * This macro subtracts a 1-byte value from the destination variable.  If there
  562. * is no op1, then the destination variable number is assumed to be in the xreg.
  563. * If there is no op2, then the value is assumed to be in the acc.
  564.     MACRO
  565. &lab    _subl    &op1,&op2
  566. &lab
  567.     if    &op1='' goto .a
  568.     ldx    #<&op1
  569. .a    if    &op2='' goto .jsr
  570.     acorm    &op2
  571. .jsr    jsr    subconl
  572.     MEND
  573.  
  574.  
  575. ***************************************
  576.  
  577.  
  578. * This macro subtracts a 2-byte value from the destination variable.  If there
  579. * is no op1, then the destination variable number is assumed to be in the xreg.
  580. * If there is no op2, then the value is assumed to be in acc,y.
  581.     MACRO
  582. &lab    _sub    &op1,&op2
  583. &lab
  584.     if    &op1='' goto .a
  585.     ldx    #<&op1
  586. .a    if    &op2='' goto .jsr
  587.     aycorm    &op2
  588.     if    ayisbyte=1 then
  589.     jsr    subconl
  590.     mexit
  591.     endif
  592. .jsr    jsr    subcon
  593.     MEND
  594.  
  595.  
  596. ***************************************
  597.  
  598.  
  599. * This macro multiplies the destination variable by a variable.  If there is
  600. * no op1, then the destination variable number is assumed to be in the xreg.
  601. * If there is no op2, then the source variable number is assumed to be in
  602. * the yreg.
  603.     MACRO
  604. &lab    _mulvar    &op1,&op2
  605. &lab
  606.     if    &op1='' goto .a
  607.     ldx    #<&op1
  608. .a    if    &op2='' goto .jsr
  609.     ldy    #<&op2
  610. .jsr    jsr    mulvar
  611.     MEND
  612.  
  613.  
  614. ***************************************
  615.  
  616.  
  617. * This macro multiplies the destination variable by a 1-byte value.  If there
  618. * is no op1, then the destination variable number is assumed to be in the xreg.
  619. * If there is no op2, then the value is assumed to be in the acc.
  620.     MACRO
  621. &lab    _mull    &op1,&op2
  622. &lab
  623.     if    &op1='' goto .a
  624.     ldx    #<&op1
  625. .a    if    &op2='' goto .jsr
  626.     acorm    &op2
  627. .jsr    jsr    mulconl
  628.     MEND
  629.  
  630.  
  631. ***************************************
  632.  
  633.  
  634. * This macro multiplies the destination variable by a 2-byte value.  If there
  635. * is no op1, then the destination variable number is assumed to be in the xreg.
  636. * If there is no op2, then the value is assumed to be in acc,y.
  637.     MACRO
  638. &lab    _mul    &op1,&op2
  639. &lab
  640.     if    &op1='' goto .a
  641.     ldx    #<&op1
  642. .a    if    &op2='' goto .jsr
  643.     aycorm    &op2
  644.     if    ayisbyte=1 then
  645.     jsr    mulconl
  646.     mexit
  647.     endif
  648. .jsr    jsr    mulcon
  649.     MEND
  650.  
  651.  
  652. ***************************************
  653.  
  654.  
  655. * This macro divides the destination variable by a variable.  If there is
  656. * no op1, then the destination variable number is assumed to be in the xreg.
  657. * If there is no op2, then the source variable number is assumed to be in
  658. * the yreg.  The remainder from the divide is in the acc,y.
  659.     MACRO
  660. &lab    _divvar    &op1,&op2
  661. &lab
  662.     if    &op1='' goto .a
  663.     ldx    #<&op1
  664. .a    if    &op2='' goto .jsr
  665.     ldy    #<&op2
  666. .jsr    jsr    divvar
  667.     MEND
  668.  
  669.  
  670. ***************************************
  671.  
  672.  
  673. * This macro divides the destination variable by a 1-byte value.  If there
  674. * is no op1, then the destination variable number is assumed to be in the xreg.
  675. * If there is no op2, then the value is assumed to be in the acc.  The
  676. * remainder from the divide is in the acc,y.
  677.     MACRO
  678. &lab    _divl    &op1,&op2
  679. &lab
  680.     if    &op1='' goto .a
  681.     ldx    #<&op1
  682. .a    if    &op2='' goto .jsr
  683.     acorm    &op2
  684. .jsr    jsr    divconl
  685.     MEND
  686.  
  687.  
  688. ***************************************
  689.  
  690.  
  691. * This macro divides the destination variable by a 2-byte value.  If there
  692. * is no op1, then the destination variable number is assumed to be in the xreg.
  693. * If there is no op2, then the value is assumed to be in acc,y.  The remainder
  694. * from the divide is in the acc,y.
  695.     MACRO
  696. &lab    _div    &op1,&op2
  697. &lab
  698.     if    &op1='' goto .a
  699.     ldx    #<&op1
  700. .a    if    &op2='' goto .jsr
  701.     aycorm    &op2
  702.     if    ayisbyte=1 then
  703.     jsr    divconl
  704.     mexit
  705.     endif
  706. .jsr    jsr    divcon
  707.     MEND
  708.  
  709.  
  710. ***************************************
  711.  
  712.  
  713. * This macro sets the current variable.  The current variable is defined by
  714. * a number in the xreg.  All runtime functions preserve the xreg, so multiple
  715. * operations can be done to the same variable without having to reload the xreg
  716. * with the variable number.
  717.     MACRO
  718. &lab    _var    &op
  719. &lab    ldx    #<&op
  720.     MEND
  721.  
  722.  
  723. ***************************************
  724.  
  725. * This macro uses a variable as a pointer and sets that variable to the value to where
  726. * that pointer currently points.  The macro preserves all registers.
  727. * The c equivalent would be (using longs instead if ints):
  728. *
  729. *    long    *ptrvar;
  730. *
  731. *    ptrvar = (long *)*ptrvar;
  732.     MACRO
  733. &lab    _vderef    &op
  734. &lab    
  735.     if    &op='' goto .jsr
  736.     ldx    #<&op
  737. .jsr    jsr    vderef
  738.     MEND
  739.  
  740.  
  741. ***************************************
  742.  
  743.  
  744. * This macro sets a variable to 0.  If there is no op1, then the destination
  745. * variable number is assumed to be in the xreg.
  746.     MACRO
  747. &lab    _set0    &op
  748. &lab    
  749.     if    &op='' goto .jsr
  750.     ldx    #<&op
  751. .jsr    jsr    setzero
  752.     MEND
  753.  
  754.  
  755. ***************************************
  756.  
  757.  
  758. * This macro sets a variable to another variable.  If there is no op1, then the
  759. * destination variable number is assumed to be in the xreg.  If there is no
  760. * op2, then the source variable number is assumed to be in the yreg.
  761.     MACRO
  762. &lab    _varcpy    &op1,&op2
  763. &lab    
  764.     if    &op1='' goto .a
  765.     ldx    #<&op1
  766. .a    if    &op2='' goto .jsr
  767.     ldy    #<&op2
  768. .jsr    jsr    seteq
  769.     MEND
  770.  
  771.  
  772. ***************************************
  773.  
  774.  
  775. * This macro sets a variable to a 1-byte value.  If there is no op1, then the
  776. * destination variable number is assumed to be in the xreg.  If there is no
  777. * op2, then the value is assumed to be in the acc.
  778.     MACRO
  779. &lab    _setl    &op1,&op2
  780. &lab    
  781.     if    &op1='' goto .a
  782.     ldx    #<&op1
  783. .a    if    &op2='' goto .jsr
  784.     acorm    &op2
  785. .jsr    jsr    setconl
  786.     MEND
  787.  
  788.  
  789. ***************************************
  790.  
  791.  
  792. * This macro sets a variable to a 2-byte value.  If there is no op1, then the
  793. * destination variable number is assumed to be in the xreg.  If there is no
  794. * op2, then the value is assumed to be in acc,y.
  795.     MACRO
  796. &lab    _set    &op1,&op2
  797. &lab    
  798.     if    &op1='' goto .a
  799.     ldx    #<&op1
  800. .a    if    &op2='' goto .jsr
  801.     aycorm    &op2
  802.     if    ayisbyte=1 then
  803.     jsr    setconl
  804.     mexit
  805.     endif
  806. .jsr    jsr    setcon
  807.     MEND
  808.  
  809.  
  810. ***************************************
  811.  
  812.  
  813. * This macro is used to set a bunch of variables to constant values.
  814. * There must be a non-zero even number of parameters.  The odd parameters
  815. * are the variables, and the even parameters are the constant values for
  816. * the preceeding parameter.  The setvars routine uses the return address
  817. * as a pointer to the data (just like the write routine).  It simply
  818. * sets the designated variable to the designated constant until it
  819. * encounters a 255 as a variable value.  A 255 is reserved for this
  820. * purpose.  This macro places a 255 at the end of the data list
  821. * automatically.
  822.     MACRO
  823. &lab    _setvars
  824. &lab    
  825.     if    &syslist[2]='' then
  826.     aerror    '_setvars:  must have at least two parameters'
  827.     mexit
  828.     endif
  829.     jsr    setvars
  830.     lcla    &i,&j,&n
  831. &i    seta    1
  832. &j    seta    2
  833. &n    seta    &nbr(&syslist)
  834. .a    if    &syslist[&j]='' then
  835.     aerror    '_setvars:  must have even number of parameters'
  836.     mexit
  837.     endif
  838.     dc.b    &syslist[&i]
  839.     if    &substr(&syslist[&j],1,1)<>'#' then
  840.     aerror    '_setvars:  variables can only be set to constants -- missing #'
  841.     mexit
  842.     endif
  843.     dc.w    &substr(&syslist[&j],2,999)
  844. &i    seta    &i+2
  845. &j    seta    &j+2
  846.     if    &i<=&n goto .a
  847.     dc.b    255
  848.     MEND
  849.  
  850.  
  851. ***************************************
  852.  
  853.  
  854. * This macro swaps the two variables if the xreg variable is bigger than the
  855. * yreg variable.  If there is no op1, then the destination variable number is
  856. * assumed to be in the xreg.  If there is no op2, then the source variable
  857. * number is assumed to be in the yreg.
  858.     MACRO
  859. &lab    _minswap    &op1,&op2    
  860. &lab    
  861.     if    &op1='' goto .a
  862.     ldx    #<&op1
  863. .a    if    &op2='' goto .jsr
  864.     ldy    #<&op2
  865. .jsr    jsr    xlty
  866.     MEND
  867.  
  868.  
  869. ***************************************
  870.  
  871.  
  872. * This macro swaps the two variables if the xreg variable is smaller than the
  873. * yreg variable.  If there is no op1, then the destination variable number is
  874. * assumed to be in the xreg.  If there is no op2, then the source variable
  875. * number is assumed to be in the yreg.
  876.     MACRO
  877. &lab    _maxswap    &op1,&op2    
  878. &lab    
  879.     if    &op1='' goto .a
  880.     ldx    #<&op1
  881. .a    if    &op2='' goto .jsr
  882.     ldy    #<&op2
  883. .jsr    jsr    xgty
  884.     MEND
  885.  
  886.  
  887. ***************************************
  888.  
  889.  
  890. * This macro does a signed compare of two variables.  The equal status is true
  891. * if the variables are equal.  If the xreg variable is greater or equal, then
  892. * the carry is set.  If the xreg variable is smaller, then the carry is clear.
  893. * If there is no op1, then the variable number is assumed to be in the xreg.
  894. * If there is no op2, then the variable number is assumed to be in the yreg.
  895.     MACRO
  896. &lab    _vsgncmp    &op1,&op2    
  897. &lab
  898.     if    &op1='' goto .a
  899.     ldx    #<&op1
  900. .a    if    &op2='' goto .jsr
  901.     ldy    #<&op2
  902. .jsr    jsr    vifsgneq
  903.     MEND
  904.  
  905.  
  906. ***************************************
  907.  
  908.  
  909. * This macro does an unsigned compare of two variables.  The equal status is
  910. * true if the variables are equal.  If the xreg variable is greater or equal,
  911. * then the carry is set.  If the xreg variable is smaller, then the carry is
  912. * clear.  If there is no op1, then the variable number is assumed to be in the
  913. * xreg.  If there is no op2, then the variable number is assumed to be in the
  914. * yreg.
  915.     MACRO
  916. &lab    _vcmp    &op1,&op2    
  917. &lab
  918.     if    &op1='' goto .a
  919.     ldx    #<&op1
  920. .a    if    &op2='' goto .jsr
  921.     ldy    #<&op2
  922. .jsr    jsr    vifequal
  923.     MEND
  924.  
  925.  
  926. ***************************************
  927.  
  928.  
  929. * This macro works the same as _vsgncmp, except that it compares a variable
  930. * against a constant or value from memory at a specified location.
  931.     MACRO
  932. &lab    _sgncmp    &op1,&op2    
  933. &lab
  934.     if    &op1='' goto .a
  935.     ldx    #<&op1
  936. .a    if    &op2='' goto .jsr
  937.     aycorm    &op2
  938.     if    ayisbyte=1 then
  939.     ldy    #0
  940.     endif
  941. .jsr    jsr    ifsgneq
  942.     MEND
  943.  
  944.  
  945. ***************************************
  946.  
  947.  
  948. * This macro works the same as _vcmp, except that it compares a variable
  949. * against a constant or value from memory at a specified location.
  950.     MACRO
  951. &lab    _cmp    &op1,&op2    
  952. &lab
  953.     if    &op1='' goto .a
  954.     ldx    #<&op1
  955. .a    if    &op2='' goto .jsr
  956.     aycorm    &op2
  957.     if    ayisbyte=1 then
  958.     ldy    #0
  959.     endif
  960. .jsr    jsr    ifequal
  961.     MEND
  962.  
  963.  
  964. ***************************************
  965. ***************************************
  966. ***************************************
  967.  
  968.  
  969. * This macro is used to seed the random number generator.  If there is
  970. * no op1, then the random seed is assumed to be in the acc,y.
  971.     MACRO
  972. &lab    _rndseed    &op
  973. &lab    
  974.     if    &op='' goto .jsr
  975.     aycorm    &op
  976.     if    ayisbyte=1 then
  977.     ldy    #0
  978.     endif
  979. .jsr    jsr    seedrandom
  980.     MEND
  981.  
  982.  
  983. ***************************************
  984.  
  985.  
  986. * This macro is used to return a random number from 0 to op - 1.  If there is
  987. * no op1, then the random number limit is assumed to be in the acc,y.
  988.     MACRO
  989. &lab    _random    &op
  990. &lab    
  991.     if    &op='' goto .jsr
  992.     aycorm    &op
  993.     if    ayisbyte=1 then
  994.     ldy    #0
  995.     endif
  996. .jsr    jsr    calcrandom
  997.     MEND
  998.  
  999.  
  1000. ***************************************
  1001. ***************************************
  1002. ***************************************
  1003.  
  1004.  
  1005. * This macro takes the value of a string and returns it in the acc,y.
  1006. * If there is no op1, then the string number is assumed to be in the xreg.
  1007.     MACRO
  1008. &lab    _strval    &op
  1009. &lab
  1010.     if    &op='' goto .jsr
  1011.     ldx    #<&op
  1012. .jsr    jsr    strval
  1013.     MEND
  1014.  
  1015.  
  1016. ***************************************
  1017.  
  1018.  
  1019. * This macro takes the value of op1 string starting at op2 character and
  1020. * returns it in the acc,y.  If there is no op1, then the string number is
  1021. * assumed to be in the xreg.  If there is no op2, then the character number
  1022. * is assumed to be in the yreg.
  1023.     MACRO
  1024. &lab    _midstrval &op1,&op2
  1025. &lab
  1026.     if    &op1='' goto .a
  1027.     ldx    #<&op1
  1028. .a    if    &op2='' goto .jsr
  1029.     ycorm    &op2
  1030. .jsr    jsr    midstrval
  1031.     MEND
  1032.  
  1033.  
  1034. ***************************************
  1035.  
  1036.  
  1037. * This macro prints the entire string.  If there is no op1, then the string
  1038. * number is assumed to be in the xreg.
  1039.     MACRO
  1040. &lab    _prstr    &op
  1041. &lab    
  1042.     if    &op='' goto .jsr
  1043.     ldx    #<&op
  1044. .jsr    jsr    prstr
  1045.     MEND
  1046.  
  1047.  
  1048. ***************************************
  1049.  
  1050.  
  1051. * This macro prints op1 string starting at the first character for op2
  1052. * characters.  If there is no op1, then the string number is assumed to be
  1053. * in the xreg.  If there is no op2, then the number of characters is assumed
  1054. * to be in the acc.
  1055.     MACRO
  1056. &lab    _prleftstr &op1,&op2
  1057. &lab
  1058.     if    &op1='' goto .a
  1059.     ldx    #<&op1
  1060. .a    if    &op2='' goto .jsr
  1061.     acorm    &op2
  1062. .jsr    jsr    prleftstr
  1063.     MEND
  1064.  
  1065.  
  1066. ***************************************
  1067.  
  1068.  
  1069. * This macro prints op1 string starting at the op2 character for op3
  1070. * characters.  If there is no op1, then the string number is assumed to be
  1071. * in the xreg.  If there is no op2, then the character number is assumed to
  1072. * be in the yreg.  If there is no op3, then the number of characters is
  1073. * assumed to be in the acc.
  1074.     MACRO
  1075. &lab    _prmidstr &op1,&op2,&op3
  1076. &lab
  1077.     if    &op1='' goto .a
  1078.     ldx    #<&op1
  1079. .a    if    &op2='' goto .b
  1080.     ycorm    &op2
  1081. .b    if    &op3='' goto .jsr
  1082.     acorm    &op3
  1083. .jsr    jsr    prmidstr
  1084.     MEND
  1085.  
  1086.  
  1087. ***************************************
  1088.  
  1089.  
  1090. * This macro copies op3 characters from op2 string to op1 string.  If there
  1091. * is no op1, then the destination string number is assumed to be in the xreg.
  1092. * If there is no op2, then the source string number is assumed to be in the
  1093. * yreg.  If there is no op3, then the number of characters is assumed to be
  1094. * in the acc.
  1095.     MACRO
  1096. &lab    _leftstrcpy &op1,&op2,&op3
  1097. &lab    
  1098.     if    &op1='' goto .a
  1099.     ldx    #<&op1
  1100. .a    if    &op2='' goto .b
  1101.     ldy    #<&op2
  1102. .b    if    &op3='' goto .jsr
  1103.     acorm    &op3
  1104. .jsr    jsr    leftstrcpy
  1105.     MEND
  1106.  
  1107.  
  1108. ***************************************
  1109.  
  1110.  
  1111. * This macro copies op2 string to op1 string.  If there is no op1, then the
  1112. * destination string number is assumed to be in the xreg.  If there is no op2,
  1113. * then the source string number is assumed to be in the yreg.
  1114.     MACRO
  1115. &lab    _strcpy &op1,&op2
  1116. &lab    
  1117.     if    &op1='' goto .a
  1118.     ldx    #<&op1
  1119. .a    if    &op2='' goto .jsr
  1120.     ldy    #<&op2
  1121. .jsr    jsr    strcpy
  1122.     MEND
  1123.  
  1124.  
  1125. ***************************************
  1126.  
  1127.  
  1128. * This macro copies op4 characters, starting at op3 character from op2 string
  1129. * to op1 string.  If there is no op1, then the destination string number is
  1130. * assumed to be in the xreg.  If there is no op2, then the source string number
  1131. * is assumed to be in the yreg.  If there is no op3, then the character number
  1132. * is assumed to be in the acc.  If there is no op4, then all characters to the
  1133. * end of the source string will be copied to the destination string.  The op4
  1134. * case is the only case where the assumed value is a particular value (#255),
  1135. * instead of what is in a register.  This is the case because there are only
  1136. * three registers.
  1137.     MACRO
  1138. &lab    _midstrcpy &op1,&op2,&op3,&op4
  1139. &lab
  1140.     if    &op4='' goto .b
  1141.     if    &op3<>'' goto .a
  1142.     pha
  1143. .a
  1144.     acorm    &op4
  1145.     sta    numtocopy
  1146.     if    &op3<>'' goto .b
  1147.     pla
  1148. .b    if    &op1='' goto .c
  1149.     ldx    #<&op1
  1150. .c    if    &op2='' goto .d
  1151.     ldy    #<&op2
  1152. .d    if    &op3='' goto .jsr
  1153.     acorm    &op3
  1154. .jsr    jsr    midstrcpy
  1155.     MEND
  1156.  
  1157.  
  1158. ***************************************
  1159.  
  1160.  
  1161. * This macro concatenates op3 characters of op2 string onto op1 string.  If
  1162. * there is no op1, then the destination string number is assumed to be in the
  1163. * xreg.  If there is no op2, then the source string number is assumed to be in
  1164. * the yreg.  If there is no op3, then the number of characters is assumed to
  1165. * be in the acc.
  1166.     MACRO
  1167. &lab    _leftstrcat &op1,&op2,&op3
  1168. &lab    
  1169.     if    &op1='' goto .a
  1170.     ldx    #<&op1
  1171. .a    if    &op2='' goto .b
  1172.     ldy    #<&op2
  1173. .b    if    &op3='' goto .jsr
  1174.     acorm    &op3
  1175. .jsr    jsr    leftstrcat
  1176.     MEND
  1177.  
  1178.  
  1179. ***************************************
  1180.  
  1181.  
  1182. * This macro concatenates op2 string onto op1 string.  If there is no op1,
  1183. * then the destination string number is assumed to be in the xreg.  If there
  1184. * is no op2, then the source string number is assumed to be in the yreg.
  1185.     MACRO
  1186. &lab    _strcat &op1,&op2
  1187. &lab    
  1188.     if    &op1='' goto .a
  1189.     ldx    #<&op1
  1190. .a    if    &op2='' goto .jsr
  1191.     ldy    #<&op2
  1192. .jsr    jsr    strcat
  1193.     MEND
  1194.  
  1195.  
  1196. ***************************************
  1197.  
  1198.  
  1199. * This macro concatenates op4 characters starting at op3 character from op2
  1200. * string onto op1 string.  If there is no op1, then the destination string
  1201. * number is assumed to be in the xreg.  If there is no op2, then the source
  1202. * string number is assumed to be in the yreg.  If there is no op3, then the
  1203. * character number is assumed to be in the acc.  If there is no op4, then all
  1204. * characters to the end of the source string will be concatenated to the
  1205. * destination string.  The op4 case is the only case where the assumed value
  1206. * is a particular value (#255), instead of what is in a register.  This is
  1207. * the case because there are only three registers.
  1208.     MACRO
  1209. &lab    _midstrcat &op1,&op2,&op3,&op4
  1210. &lab
  1211.     if    &op4='' goto .b
  1212.     if    &op3<>'' goto .a
  1213.     pha
  1214. .a
  1215.     acorm    &op4
  1216.     sta    numtocopy
  1217.     if    &op3<>'' goto .b
  1218.     pla
  1219. .b    if    &op1='' goto .c
  1220.     ldx    #<&op1
  1221. .c    if    &op2='' goto .d
  1222.     ldy    #<&op2
  1223. .d    if    &op3='' goto .jsr
  1224.     acorm    &op3
  1225. .jsr    jsr    midstrcat
  1226.     MEND
  1227.  
  1228.  
  1229. ***************************************
  1230.  
  1231.  
  1232. * This macro is used to take some literal string data and place it into
  1233. * a string.  It works very much like the write routine, except that it
  1234. * copies the characters into a string instead of printing them.  Operand
  1235. * 1 is the string variable, if there is one designated.  If there is not
  1236. * one designated, then the x-reg is assumed to already hold it.  There
  1237. * then must be a second parameter.  This parameter would be string data.
  1238. * There may be other parameters, which would also hold string data.
  1239. * When all data parameters are used by this macro, the macro then places
  1240. * a 0 terminator to indicate the end of the literal data.
  1241.     MACRO
  1242. &lab    _litstr
  1243. &lab    
  1244.     if    &syslist[2]='' then
  1245.     aerror    '_litstr:  must have a second parameter'
  1246.     mexit
  1247.     endif
  1248.     if    &syslist[1]='' goto .jsr
  1249.     ldx    #<&syslist[1]
  1250. .jsr    jsr    litstr
  1251.     lcla    &i,&n
  1252. &i    seta    2
  1253. &n    seta    &nbr(&syslist)
  1254. .a    dc.b    &syslist[&i]
  1255. &i    seta    &i+1
  1256.     if    &i<=&n goto .a
  1257.     dc.b    0
  1258.     MEND
  1259.  
  1260.  
  1261. ***************************************
  1262.  
  1263.  
  1264. * This macro returns the op2th character of op1 string.  If there is no op1,
  1265. * then the destination string number is assumed to be in the xreg.  If there
  1266. * is no op2, then the character number is assumed to be in the acc.
  1267.     MACRO
  1268. &lab    _strchr &op1,&op2
  1269. &lab    
  1270.     if    &op1='' goto .a
  1271.     ldx    #<&op1
  1272. .a    if    &op2='' goto .jsr
  1273.     acorm    &op2
  1274. .jsr    jsr    strchr
  1275.     MEND
  1276.  
  1277.  
  1278. ***************************************
  1279.  
  1280.  
  1281. * This macro returns the physical location of op1 string in memory.  The
  1282. * string location is returned in acc,y.If there is no op1, then the
  1283. * destination string number is assumed to be in the xreg.
  1284.     MACRO
  1285. &lab    _strloc &op1
  1286. &lab    
  1287.     if    &op1='' goto .jsr
  1288.     ldx    #<&op1
  1289. .jsr    jsr    strloc
  1290.     MEND
  1291.  
  1292.  
  1293. ***************************************
  1294.  
  1295.  
  1296.     MACRO
  1297. &lab    _cstr
  1298. &lab    
  1299.     if    &syslist[1]='' then
  1300.     aerror    '_write:  must have at least one parameter'
  1301.     mexit
  1302.     endif
  1303.     lcla    &i,&n
  1304. &i    seta    1
  1305. &n    seta    &nbr(&syslist)
  1306. .a    dc.b    &syslist[&i]
  1307. &i    seta    &i+1
  1308.     if    &i<=&n goto .a
  1309.     dc.b    0
  1310.     MEND
  1311.  
  1312.  
  1313. ***************************************
  1314. ***************************************
  1315. ***************************************
  1316.  
  1317.  
  1318. * This macro sets the read data pointer.  If there is no op, then the address
  1319. * for reading data is assumed to be in the acc,y.
  1320.     MACRO
  1321. &lab    _restore    &op
  1322. &lab
  1323.     if    &op='' goto .jsr
  1324.     aycorm    &op
  1325.     if    ayisbyte=1 then
  1326.     ldy    #0
  1327.     endif
  1328. .jsr    jsr    restore
  1329.     MEND
  1330.  
  1331.  
  1332. ***************************************
  1333.  
  1334.  
  1335. * This macro reads an int from the current data pointer and advances the
  1336. * pointer by two bytes.  If there is no op1, then the destination variable
  1337. * number is assumed to be in the xreg.
  1338.     MACRO
  1339. &lab    _readint    &op
  1340. &lab    
  1341.     if    &op='' goto .jsr
  1342.     ldx    #<&op
  1343. .jsr    jsr    readint
  1344.     MEND
  1345.  
  1346.  
  1347. ***************************************
  1348.  
  1349.  
  1350. * This macro reads string data into the designated string until the
  1351. * end-of-string character is encountered.  The data pointer is then set to
  1352. * point after this end-of-string character.  If there is no op1, then the
  1353. * destination string number is assumed to be in the xreg.
  1354.     MACRO
  1355. &lab    _readstr    &op
  1356. &lab    
  1357.     if    &op='' goto .jsr
  1358.     ldx    #<&op
  1359. .jsr    jsr    readstr
  1360.     MEND
  1361.  
  1362.  
  1363. ***************************************
  1364.  
  1365.  
  1366. * This macro is used to set the end-of-string character for _readstr.  If
  1367. * there is no op1, then the _readstr ending character is assumed to be in
  1368. * the acc.
  1369.     MACRO
  1370. &lab    _readend    &op
  1371. &lab    
  1372.     if    &op='' goto .jsr
  1373.     acorm    &op
  1374. .jsr    jsr    readend
  1375.     MEND
  1376.  
  1377.  
  1378. ***************************************
  1379. ***************************************
  1380. ***************************************
  1381.  
  1382.  
  1383. * This macro is used to define some memory as an array of up to
  1384. * 4 dimensions.  The first parameter is the location of the
  1385. * array, or where the location of the array is stored.  The second
  1386. * parameter is the size of the elements, (b)yte or (w)ord.  The 
  1387. * third parameter is the first dimension.  The macro and routines
  1388. * actually ignore this dimension, since it would only be used for
  1389. * range checking anyway.  The fourth through sixth parameters are
  1390. * optional.  The more parameters, the more dimensions in the array.
  1391.     MACRO
  1392. &lab    _array    &loc,&elesize,&op1,&op2,&op3,&op4
  1393. &lab    
  1394.     if    &loc='' goto .a
  1395.     aycorm    &loc
  1396.     if    ayisbyte=1 then
  1397.     ldy    #0
  1398.     endif
  1399. .a    jsr    arraybase
  1400.     if    &op4='' goto .b
  1401.     if    &substr(&op4,1,1)<>'#' then
  1402. .err    aerror    '_array:  dimensions must be constants --  parameter must be preceeded by a #'
  1403.     mexit
  1404.     endif
  1405. .b    if    &op3='' goto .c
  1406.     if    &substr(&op3,1,1)<>'#' goto .err
  1407. .c    if    &op2='' goto .d
  1408.     if    &substr(&op2,1,1)<>'#' goto .err
  1409. .d    if    &op1='' goto .e
  1410.     if    &substr(&op1,1,1)<>'#' goto .err
  1411. .e    if    &substr(&elesize,1,1)='b' goto .byte
  1412.     if    &substr(&elesize,1,1)='B' goto .byte
  1413.     if    &substr(&elesize,1,1)='w' goto .word
  1414.     if    &substr(&elesize,1,1)='W' goto .word
  1415.     aerror    '_array:  element size can only be byte or word (b,w)'
  1416. .word    if    &op4>'' goto .w4
  1417.     if    &op3>'' goto .w3
  1418.     if    &op2>'' goto .w2
  1419.     mexit
  1420. .w2    lda    #<&substr(&op2,2,999)*2
  1421.     ldy    #>&substr(&op2,2,999)*2
  1422.     jsr    dim1size
  1423.     mexit
  1424. .w3    lda    #<&substr(&op2,2,999)*&substr(&op3,2,999)*2
  1425.     ldy    #>&substr(&op2,2,999)*&substr(&op3,2,999)*2
  1426.     jsr    dim1size
  1427.     lda    #<&substr(&op3,2,999)*2
  1428.     ldy    #>&substr(&op3,2,999)*2
  1429.     jsr    dim2size
  1430.     mexit
  1431. .w4    lda    #<&substr(&op2,2,999)*&substr(&op3,2,999)*&substr(&op4,2,999)*2
  1432.     ldy    #>&substr(&op2,2,999)*&substr(&op3,2,999)*&substr(&op4,2,999)*2
  1433.     jsr    dim1size
  1434.     lda    #<&substr(&op3,2,999)*&substr(&op4,2,999)*2
  1435.     ldy    #>&substr(&op3,2,999)*&substr(&op4,2,999)*2
  1436.     jsr    dim2size
  1437.     lda    #<&substr(&op4,2,999)*2
  1438.     ldy    #>&substr(&op4,2,999)*2
  1439.     jsr    dim3size
  1440.     mexit
  1441. .byte    if    &op4>'' goto .b4
  1442.     if    &op3>'' goto .b3
  1443.     if    &op2>'' goto .b2
  1444. .b2    lda    #<&substr(&op2,2,999)
  1445.     ldy    #>&substr(&op2,2,999)
  1446.     jsr    dim1size
  1447.     mexit
  1448. .b3    lda    #<&substr(&op2,2,999)*&substr(&op3,2,999)
  1449.     ldy    #>&substr(&op2,2,999)*&substr(&op3,2,999)
  1450.     jsr    dim1size
  1451.     lda    #<&substr(&op3,2,999)
  1452.     ldy    #>&substr(&op3,2,999)
  1453.     jsr    dim2size
  1454.     mexit
  1455. .b4    lda    #<&substr(&op2,2,999)*&substr(&op3,2,999)*&substr(&op4,2,999)
  1456.     ldy    #>&substr(&op2,2,999)*&substr(&op3,2,999)*&substr(&op4,2,999)
  1457.     jsr    dim1size
  1458.     lda    #<&substr(&op3,2,999)*&substr(&op4,2,999)
  1459.     ldy    #>&substr(&op3,2,999)*&substr(&op4,2,999)
  1460.     jsr    dim2size
  1461.     lda    #<&substr(&op4,2,999)
  1462.     ldy    #>&substr(&op4,2,999)
  1463.     jsr    dim3size
  1464.     MEND
  1465.  
  1466.  
  1467. ***************************************
  1468.  
  1469.  
  1470. * This macro is used to index into the current array (defined by _array).
  1471. * The whole goal of the array handling is to index down to the row level.
  1472. * Once at the row level, you use the right-most subscript to index into
  1473. * that row.  This makes working on a row very fast, since all subscripts
  1474. * are not involved each time.  So, _index would be used for all subscripts
  1475. * except for the last subscript.  The parameter can either be a constant,
  1476. * (preceeded with a #) or can be a location in ram that holds the index
  1477. * (preceeded with an *).
  1478.     MACRO
  1479. &lab    _index    &op1,&op2,&op3
  1480. &lab
  1481.     if    &op1='' goto .a
  1482.     aycorm    &op1
  1483.     if    ayisbyte=1 then
  1484.     jsr    arraylindx1
  1485.     else
  1486.     jsr    arrayindx1
  1487.     endif
  1488. .a    if    &op2='' goto .b
  1489.     aycorm    &op2
  1490.     if    ayisbyte=1 then
  1491.     jsr    arraylindx2
  1492.     else
  1493.     jsr    arrayindx2
  1494.     endif
  1495. .b    if    &op3='' goto .c
  1496.     aycorm    &op3
  1497.     if    ayisbyte=1 then
  1498.     jsr    arraylindx3
  1499.     else
  1500.     jsr    arrayindx3
  1501.     endif
  1502. .c    MEND
  1503.  
  1504.  
  1505. ***************************************
  1506.  
  1507.  
  1508. * This macro works the same as _index, except that the index is stored
  1509. * in the variable indicated.
  1510.     MACRO
  1511. &lab    _vindex    &op1,&op2,&op3
  1512. &lab
  1513.     if    &op1='' goto .a
  1514.     ldy    #<&op1
  1515.     jsr    varyindx1
  1516. .a    if    &op2='' goto .b
  1517.     ldy    #<&op2
  1518.     jsr    varyindx2
  1519. .b    if    &op3='' goto .c
  1520.     ldy    #<&op3
  1521.     jsr    varyindx3
  1522. .c    MEND
  1523.  
  1524.  
  1525. ***************************************
  1526.  
  1527.  
  1528. * This macro gets a byte from the working row of the current array.
  1529. * The final index parameter is used to index into this row.
  1530.     MACRO
  1531. &lab    _getb    &op1,&op2
  1532. &lab
  1533.     if    &op1='' goto .a
  1534.     ldx    #<&op1
  1535. .a    if    &op2='' goto .jsr
  1536.     aycorm    &op2
  1537.     if    ayisbyte=1 then
  1538.     jsr    getbytel
  1539.     mexit
  1540.     endif
  1541. .jsr    jsr    getbyte
  1542.     MEND
  1543.  
  1544.  
  1545. ***************************************
  1546.  
  1547.  
  1548. * This macro gets a byte from the working row of the current array.
  1549. * The final index parameter is used to index into this row.
  1550.     MACRO
  1551. &lab    _getbl    &op1,&op2
  1552. &lab
  1553.     if    &op1='' goto .a
  1554.     ldx    #<&op1
  1555. .a    if    &op2='' goto .jsr
  1556.     acorm    &op2
  1557. .jsr    jsr    getbytel
  1558.     MEND
  1559.  
  1560.  
  1561. ***************************************
  1562.  
  1563.  
  1564. * This macro is works the same as _getb, except that the index is
  1565. * stored in a variable.
  1566.     MACRO
  1567. &lab    _vgetb    &op1,&op2
  1568. &lab
  1569.     if    &op1='' goto .a
  1570.     ldx    #<&op1
  1571. .a    if    &op2='' goto .jsr
  1572.     ldy    #<&op2
  1573. .jsr    jsr    vgetbyte
  1574.     MEND
  1575.  
  1576.  
  1577. ***************************************
  1578.  
  1579.  
  1580. * This macro is the same as _getb, except that it gets a word.
  1581.     MACRO
  1582. &lab    _getw    &op1,&op2
  1583. &lab
  1584.     if    &op1='' goto .a
  1585.     ldx    #<&op1
  1586. .a    if    &op2='' goto .jsr
  1587.     aycorm    &op2
  1588.     if    ayisbyte=1 then
  1589.     jsr    getwordl
  1590.     mexit
  1591.     endif
  1592. .jsr    jsr    getword
  1593.     MEND
  1594.  
  1595.  
  1596. ***************************************
  1597.  
  1598.  
  1599. * This macro is the same as _getb, except that it gets a word.
  1600.     MACRO
  1601. &lab    _getwl    &op1,&op2
  1602. &lab
  1603.     if    &op1='' goto .a
  1604.     ldx    #<&op1
  1605. .a    if    &op2='' goto .jsr
  1606.     acorm    &op2
  1607. .jsr    jsr    getwordl
  1608.     MEND
  1609.  
  1610.  
  1611. ***************************************
  1612.  
  1613.  
  1614. * This macro is the same as _vgetb, except that it gets a word.
  1615.     MACRO
  1616. &lab    _vgetw    &op1,&op2
  1617. &lab
  1618.     if    &op1='' goto .a
  1619.     ldx    #<&op1
  1620. .a    if    &op2='' goto .jsr
  1621.     ldy    #<&op2
  1622. .jsr    jsr    vgetword
  1623.     MEND
  1624.  
  1625.  
  1626. ***************************************
  1627.  
  1628.  
  1629. * This macro is the same as _getb, except that it stores a byte.
  1630.     MACRO
  1631. &lab    _putb    &op1,&op2
  1632. &lab
  1633.     if    &op1='' goto .a
  1634.     ldx    #<&op1
  1635. .a    if    &op2='' goto .jsr
  1636.     aycorm    &op2
  1637.     if    ayisbyte=1 then
  1638.     jsr    putbytel
  1639.     mexit
  1640.     endif
  1641. .jsr    jsr    putbyte
  1642.     MEND
  1643.  
  1644.  
  1645. ***************************************
  1646.  
  1647.  
  1648. * This macro is the same as _getb, except that it stores a byte.
  1649.     MACRO
  1650. &lab    _putbl    &op1,&op2
  1651. &lab
  1652.     if    &op1='' goto .a
  1653.     ldx    #<&op1
  1654. .a    if    &op2='' goto .jsr
  1655.     acorm    &op2
  1656. .jsr    jsr    putbytel
  1657.     MEND
  1658.  
  1659.  
  1660. ***************************************
  1661.  
  1662.  
  1663. * This macro is the same as _vgetb, except that it stores a byte.
  1664.     MACRO
  1665. &lab    _vputb    &op1,&op2
  1666. &lab
  1667.     if    &op1='' goto .a
  1668.     ldx    #<&op1
  1669. .a    if    &op2='' goto .jsr
  1670.     ldy    #<&op2
  1671. .jsr    jsr    vputbyte
  1672.     MEND
  1673.  
  1674.  
  1675. ***************************************
  1676.  
  1677.  
  1678. * This macro is the same as _getw, except that it stores a word.
  1679.     MACRO
  1680. &lab    _putw    &op1,&op2
  1681. &lab
  1682.     if    &op1='' goto .a
  1683.     ldx    #<&op1
  1684. .a    if    &op2='' goto .jsr
  1685.     aycorm    &op2
  1686.     if    ayisbyte=1 then
  1687.     jsr    putwordl
  1688.     mexit
  1689.     endif
  1690. .jsr    jsr    putword
  1691.     MEND
  1692.  
  1693.  
  1694. ***************************************
  1695.  
  1696.  
  1697. * This macro is the same as _getw, except that it stores a word.
  1698.     MACRO
  1699. &lab    _putwl    &op1,&op2
  1700. &lab
  1701.     if    &op1='' goto .a
  1702.     ldx    #<&op1
  1703. .a    if    &op2='' goto .jsr
  1704.     acorm    &op2
  1705. .jsr    jsr    putwordl
  1706.     MEND
  1707.  
  1708.  
  1709. ***************************************
  1710.  
  1711.  
  1712. * This macro is the same as _vgetw, except that it stores a word.
  1713.     MACRO
  1714. &lab    _vputw    &op1,&op2
  1715. &lab
  1716.     if    &op1='' goto .a
  1717.     ldx    #<&op1
  1718. .a    if    &op2='' goto .jsr
  1719.     ldy    #<&op2
  1720. .jsr    jsr    vputword
  1721.     MEND
  1722.